<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * 商品类
 * 
 * @author  : $Author: spike $
 * @date    : $Date: 2014-05-07 09:39:29 +0800 (三, 2014-05-07) $
 * @version : $Id: goods_model.php 96 2014-05-07 01:39:29Z spike $
 * @rev     : $Revision: 96 $
 */
class Goods_model extends CI_Model
{
    static $MAX_IMG;
    static $IMG_PATH;
    static $MAX_UPLOAD_ITEM;

    public function __construct()
    {
        parent::__construct();
        self::$MAX_UPLOAD_ITEM = 50;
        self::$MAX_IMG         = 1;
        self::$IMG_PATH        = FRONTEND_DATA_PATH."/goods/";
    }

    // --------------------------------------------------------------------
    
    /**
     * [返回一个新的商品编号]
     * @return [string/false]
     */
    public function gen_goods_sn()
    {
        $prefix     = 'G';
        $pad_length = 4;

        $this->load->dao('Goods_dao');
        $goods_sn = $this->Goods_dao->get_max_goods_sn();
        if( ! $goods_sn )
            return $prefix.str_pad(1, $pad_length, 0, STR_PAD_LEFT);

        if( ! validate($goods_sn, 'goods_sn') )
            return FALSE;

        $num = intval(str_replace($prefix, '', $goods_sn));
        if($num >= 9999)
            return FALSE;

        $num++;
        return $prefix.str_pad($num, $pad_length, 0, STR_PAD_LEFT);
    }

    // --------------------------------------------------------------------
    
    /**
     * [获得一个商品]
     * @param  [string]     $goods_sn
     * @param  [bool]       $enable        [是否排除"关闭状态"]
     * @return [array/false]
     */
    public function get_goods($goods_sn, $enable = TRUE, $with_attr = FALSE, $with_desc = FALSE )
    {
        if( ! validate($goods_sn, 'GOODS_SN') )
        {
            $this->set_error("获取商品失败：商品编码[{$goods_sn}]格式不正确。");
            return FALSE;
        }
        
        $where = array(
            'goods_sn'  => $goods_sn,
            'is_delete' => UNDELETED,
        );
        if($enable === TRUE)
        {
            $where['status'] = GOODS_STATUS_ON;
        }

        $this->load->dao('Goods_dao');
        $goods = $this->Goods_dao->get_one($where);
        if( ! $goods)
        {
            $this->set_error("获取商品失败：无法找到商品。[{$goods_sn}]");
            return FALSE;
        }

        if( $with_attr === TRUE )
        {
            $this->load->dao('Goods_attr_dao');
            $attr = $this->Goods_attr_dao->get(
                array(
                    'goods_sn' => $goods_sn,
                    'is_delete'=> UNDELETED,
                ),
                array(
                    'attr_id','attr_value_id'
                )
            );
            foreach ($attr as $a) 
            {
                $goods['attr'][$a['attr_id']][] = $a['attr_value_id'];
            }
        }

        if( $with_desc === TRUE )
        {
            $this->load->dao('Goods_desc_dao');
            $desc = $this->Goods_desc_dao->get_one(
                array(
                'is_delete' => UNDELETED,
                'goods_sn'  => $goods_sn,
                'type'      => GOODS_DESC_TYPE_NORMAL,
                ),
                array(
                    'desc'
                )
            );
            $goods['desc'] = htmlspecialchars_decode($desc['desc']);
        }

        return $goods;
    }

    // --------------------------------------------------------------------

    /**
     * [分页浏览]
     * @param  [array]  $params  [条件]
     * @param  [int]    $page    [当前页]
     * @param  [int]    $size    [页数，只允许app_config中"pagesize"的值]
     * @param  [string] $orderby [排序]
     * @return [array]
     */
    public function browse_goods($params, $page = NULL, $size = NULL, $orderby = '`goods_id` DESC')
    {
        $output = array(
            'size' => 0,
            'data' => array(),
            'total'=> 0,
        );

        $where = array(
            'is_delete' => UNDELETED,
        );
        $where_in = NULL;

        if( ! empty($params['goods_sn']) )
        {
            $where['`goods_sn` LIKE'] = "%".xss_clean(trim($params['goods_sn']))."%";
        }

        if( ! empty($params['name']) )
        {
            $where['`name` LIKE'] = "%".xss_clean(trim($params['name']))."%";
        }

        if( ! empty($params['subname']) )
        {
            $where['`subname` LIKE'] = "%".xss_clean(trim($params['subname']))."%";
        }

        if( validate($params['attr_id'], 'attr_id') && validate($params['attr_value_id'], 'attr_value_id') )
        {
            $this->load->dao('Goods_attr_dao');
            $goods_sn = $this->Goods_attr_dao->get(
                array(
                    'is_delete'     => UNDELETED,
                    'attr_id'       => $params['attr_id'],
                    'attr_value_id' => $params['attr_value_id'],
                ),
                array('goods_sn')
            );
            $goods_sns   = array_pick($goods_sn, 'goods_sn');

            $where_in['goods_sn'] = $goods_sns;
        }

        if( validate($params['brand_sn'], 'brand_sn') )
        {
            $where['`brand_sn`'] = $params['brand_sn'];
        }

        if( validate($params['category_id'], 'category_id') )
        {
            $this->load->dao('Category_dao');
            $category_ids = $this->Category_dao->get(
                array(
                    'is_delete' => UNDELETED,
                    'parent_id' => $params['category_id'],
                ),
                array('category_id')
            );
            $category_ids   = array_pick($category_ids, 'category_id');
            $category_ids[] = $params['category_id'];

            $where_in['category_id'] = $category_ids;
        }

        if( ! empty($params['status']) )
        {
            $goods_status = $this->config->item('goods_status');
            if( $goods_status["{$params['status']}"] )
                $where['status'] = $params['status'];
        }

        if( ! empty($params['type']) )
        {
            $goods_type = $this->config->item('goods_type');
            if( $goods_type["{$params['type']}"] )
                $where['type'] = $params['type'];
        }
      
        if( ! empty($params['create_time_start']) && strtotime($params['create_time_start']) )
        {
            $where['`create_time` >'] = $params['create_time_start'];
        }

        if( ! empty($params['create_time_end']) && strtotime($params['create_time_end']) )
        {
            $where['`create_time` <'] = $params['create_time_end'];
        }

        if( ! empty($params['update_time_start']) && strtotime($params['update_time_start']) )
        {
            $where['`update_time` >'] = $params['update_time_start'];
        }

        if( ! empty($params['update_time_end']) && strtotime($params['update_time_end']) )
        {
            $where['`update_time` <'] = $params['update_time_end'];
        }
        
        $pagesize = $this->config->item('pagesize');
        $size     = isset($pagesize[$size]) ? $size : 10;
        $offset   = intval(($page-1)*$size) > 0 ? intval(($page-1)*$size) : 0;
        $total    = 0;

        $this->load->dao('Goods_dao');
        $data = $this->Goods_dao->get_in(
            $where_in,
            $where, 
            '*', 
            $orderby, 
            $size, 
            $offset, 
            TRUE, 
            $total
        );

        $output['size']  = $size; 
        $output['data']  = $data; 
        $output['total'] = $total;

        return $output;
    }

    // --------------------------------------------------------------------
    
    /**
     * [改变商品状态]
     * 
     * @param  [string]  $goods_sn   [编码]
     * @param  [string]  $act        [操作类型]
     * @return [bool]
     */
    public function change_goods_status($goods_sn, $act)
    {   
        if( ! $goods = $this->get_goods($goods_sn, FALSE))
        {
            $this->set_error("修改商品状态失败：无法找到商品[{$goods_sn}]。");
            return FALSE;
        }

        // 初始化数据
        $_status       = NULL;  //修改的状态
        $_allow_status = NULL;  //允许修改的状态
        $_update       = NULL;  //更新的数据
        
        switch (strtolower(trim($act)))
        {
            case 'on':
                    $_status       = GOODS_STATUS_ON;
                    $_allow_status = array(GOODS_STATUS_OFF);
                    $_update       = array(
                        'status'       => $_status,
                        'update_time'  => now_str(),
                        'update_admin' => login_info('admin_id'), 
                    );
                break;

            case 'off':
                    $_status       = GOODS_STATUS_OFF;
                    $_allow_status = array(GOODS_STATUS_ON);
                    $_update       = array(
                        'status'       => $_status,
                        'update_time'  => now_str(),
                        'update_admin' => login_info('admin_id'), 
                    );
                break;

            default:
                    $this->set_error("修改商品状态失败：未知的操作[{$act}]。");
                    return FALSE;
                break;
        }

        $status      = $this->config->item('goods_status');
        $status_name = (string)$status[$_status];

        // 验证状态
        $current_status = (int)$goods['status'];
        if($current_status === $_status)
        {
            $this->set_error("修改商品状态失败：无需修改。");
            return FALSE;
        }

        if( $_allow_status && ! in_array($current_status, $_allow_status))
        {
            $this->set_error("修改商品状态失败：不允许被修改为[{$status_name}]状态。");
            return FALSE;
        }

       
        // 只有符合条件才会被修改
        $this->load->dao('Goods_dao');
        $affected_row = $this->Goods_dao->update_in(
            $_update,
            array('status'   => $_allow_status),
            array('goods_sn' => $goods_sn)
        );
        if($affected_row<=0)
        {
            $this->set_error("修改商品状态失败：无法写入数据库。");
            return FALSE;
        }

        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * [批量改变状态, 成功返回影响数字]
     * 
     * @param  [array]    $goods_sns  [商品编码]
     * @param  [string] $act          [操作类型]
     * @return [int/bool]
     */
    public function batch_change_goods_status($goods_sns, $act)
    {   
        if( ! is_array($goods_sns) || count($goods_sns) <= 0 )
        {
            $this->set_error("批量修改商品状态失败：请提供有效的商品编号。");
            return FALSE;
        }

        foreach ($goods_sns as $g) 
        {
            if( ! validate($g, "goods_sn") )
            {
                $this->set_error("批量修改商品状态失败：[{$g}] 不是一个正确的商品编号。");
                return FALSE;
            }
        }

        // 初始化数据
        $_status       = NULL;  //修改的状态
        $_allow_status = NULL;  //允许修改的状态
        
        switch (strtolower(trim($act)))
        {
            case 'on':
                    $_status       = GOODS_STATUS_ON;
                    $_allow_status = array(GOODS_STATUS_OFF);
                break;

            case 'off':
                    $_status       = GOODS_STATUS_OFF;
                    $_allow_status = array(GOODS_STATUS_ON);
                break;

            default:
                    $this->set_error("批量修改商品状态失败：未知的操作[{$act}]。");
                    return FALSE;
                break;
        }

        $status      = $this->config->item('goods_status');
        $status_name = (string)$status[$_status];

        // 只有符合条件才会被修改
        $this->load->dao('Goods_dao');
        $affected_row = $this->Goods_dao->batch_change_goods_status(
            $goods_sns,
            $_status,
            $_allow_status
        );

        return $affected_row;
    }

    /**
     * [批量改变商品品牌, 成功返回影响数字]
     * 
     * @param  [array]    $goods_sns  [商品编码]
     * @param  [string]   $brand_sn   [品牌编码]
     * @return [int/bool]
     */
    public function batch_change_goods_brand($goods_sns, $brand_sn)
    {   
        if( ! is_array($goods_sns) || count($goods_sns) <= 0 )
        {
            $this->set_error("批量修改商品品牌失败：请提供有效的商品编号。");
            return FALSE;
        }

        foreach ($goods_sns as $g) 
        {
            if( ! validate($g, "goods_sn") )
            {
                $this->set_error("批量修改商品品牌失败：[{$g}] 不是一个正确的商品编号。");
                return FALSE;
            }
        }

        $this->load->model('Brand_model');
        if( ! $this->Brand_model->get_brand($brand_sn))
        {
            $this->set_error("批量修改商品品牌失败：无法找到指定的品牌。[{$brand_sn}]");
            return FALSE;
        }
        
        // 只有符合条件才会被修改
        $this->load->dao('Goods_dao');
        $affected_row = $this->Goods_dao->update_in(
            array('brand_sn' => $brand_sn),
            array('goods_sn' => $goods_sns),
            array('is_delete'=> UNDELETED, 'status'=>GOODS_STATUS_ON)
        );

        return $affected_row;
    }

    // --------------------------------------------------------------------

    /**
     * [新增商品]
     * @param  [array]  $params [所有信息的数组]
     * @return [bool]
     */
    public function add_goods(Array $params)
    {
        $params = array(
            'name'        => $params['name']        ? xss_clean(trim($params['name']))        : NULL,
            'subname'     => $params['subname']     ? xss_clean(trim($params['subname']))     : NULL,
            'type'        => $params['type']        ? xss_clean(trim($params['type']))        : NULL,
            'brand_sn'    => $params['brand_sn']    ? xss_clean(trim($params['brand_sn']))    : NULL,
            'category_id' => $params['category_id'] ? xss_clean(trim($params['category_id'])) : NULL,
            'base_price'  => $params['base_price'] ? xss_clean(trim($params['base_price']))   : NULL,
            'attr_values' => $params['attr_values'] ? (array)$params['attr_values']           : NULL,
            'desc'        => $params['desc']        ? trim($params['desc'])                   : NULL,
        );
        
        $goods        = array();
        $goods_attr   = array();
        $category     = array();
        $goods_desc   = array();
        $goods_sn     = '';
        $create_admin = login_info('admin_id');
        $create_time  = now_str();

        /* 校验分类开始 */
        if( ! validate($params['category_id'], 'category_id') )
        {
            $this->set_error("新增商品失败：分类ID不正确。[{$params['category_id']}]。");
            return FALSE;
        }
        $this->load->dao('Category_dao');
        $category = $this->Category_dao->get_one(array(
            'category_id' => $params['category_id'],
            'is_delete'   => UNDELETED,
            'status'      => CATEGORY_STATUS_ON,
        ));
        if( ! $category )
        {
            $this->set_error("新增商品失败：分类ID不正确。[{$params['category_id']}]。");
            return FALSE;
        }
        $goods['category_id'] = $params['category_id'];
        /* 校验分类结束 */

        /* 校验名开始 */
        if( ! validate_length($params['name'], 1, 50) )
        {
            $this->set_error("新增商品失败：商品名最少1个字最多50个字。[{$params['name']}]。");
            return FALSE;
        }

        $this->load->dao('Goods_dao');
        $count = $this->Goods_dao->count(array(
            'status'    => GOODS_STATUS_ON,
            'name'      => $params['name'],
            'is_delete' => UNDELETED,
        ));

        if( $count > 0)
        {
            $this->set_error("新增商品失败：商品名已存在。[{$params['name']}]。");
            return FALSE;
        }
        $goods['name'] = $params['name'];
        /* 校验名结束 */

        /* 校验英文名开始 */
        if( ! validate_length($params['subname'], 1, 50) )
        {
            $this->set_error("新增商品失败：商品英文名最少1个字最多50个字。[{$params['subname']}]。");
            return FALSE;
        }

        $this->load->dao('Goods_dao');
        $count = $this->Goods_dao->count(array(
            'status'    => GOODS_STATUS_ON,
            'subname'   => $params['subname'],
            'is_delete' => UNDELETED,
        ));

        if( $count > 0)
        {
            $this->set_error("新增商品失败：商品英文名已存在。[{$params['subname']}]。");
            return FALSE;
        }
        $goods['subname'] = $params['subname'];
        /* 校验英文名结束 */

        /* 校验价格开始 */
        if( isset($params['base_price']) )
        {
            $base_price = moneyval($params['base_price']);
            if( $base_price < 0 )
            {
                $this->set_error("新增商品失败：商品价格必须大于零。[{$params['base_price']}]。");
                return FALSE;
            }
            $goods['base_price'] = $base_price;
        }
       
        /* 校验价格结束 */

        /* 校验类型开始 */
        $goods_type = $this->config->item('goods_type');
        if( ! $goods_type[$params['type']] )
        {
            $this->set_error("新增商品失败：未知的商品类型。[{$params['type']}]。");
            return FALSE;
        }
        $goods['type'] = $params['type'];
        /* 校验类型结束 */

        /* 校验品牌开始 */
        if( ! validate($params['brand_sn'], 'brand_sn') )
        {
            $this->set_error("新增商品失败：品牌编码不正确。[{$params['brand_sn']}]。");
            return FALSE;
        }
        $this->load->dao('Brand_dao');
        $count = $this->Brand_dao->count(array(
            'brand_sn' => $params['brand_sn'],
            'status'   => BRAND_STATUS_ON,
            'is_delete'=> UNDELETED,
        ));
        if( $count <= 0 )
        {
            $this->set_error("新增商品失败：无法找到品牌。[{$params['brand_sn']}]。");
            return FALSE;
        }
        $goods['brand_sn'] = $params['brand_sn'];
        /* 校验品牌结束 */

        /* 校验属性开始 */
        if( $params['attr_values'] )
        {
            $this->load->dao('Attr_group_dao');
            $attr_group = $this->Attr_group_dao->get_one(array(
                'attr_group_id' => $category['attr_group_id'],
                'status'        => ATTR_GROUP_STATUS_ON,
                'is_delete'     => UNDELETED,
            ));

            if( ! $attr_group )
            {
                $this->set_error("新增商品失败：无法找到属性模版。[{$category['attr_group_id']}]。");
                return FALSE;
            }

            $this->load->dao('Attr_dao');
            $attrs = $this->Attr_dao->get(
                array(
                    'attr_group_id' => $category['attr_group_id'],
                    'status'        => ATTR_STATUS_ON,
                    'is_delete'     => UNDELETED,
                ),
                array(
                    'attr_id',
                )
            );
            $attr_ids = array_pick($attrs, 'attr_id');

            $this->load->dao('Attr_value_dao');
            $attr_values = $this->Attr_value_dao->get_in(
                array('attr_id' => $attr_ids),
                array(
                    'status'        => ATTR_VALUE_STATUS_ON,
                    'is_delete'     => UNDELETED,
                ),
                array(
                    'attr_id',
                    'attr_value_id'
                )
            );

            array_change_key($attr_values, 'attr_value_id');

            foreach ($params['attr_values'] as $p) 
            {
                if( ! validate($p, 'ATTR_VALUE_ID') )
                {
                    $this->set_error("新增商品失败：属性值ID不正确。[{$p}]。");
                    return FALSE;
                }

                if( ! $attr_values[$p] )
                {
                    $this->set_error("新增商品失败：商品没有这个属性值。[{$p}]。");
                    return FALSE;
                }

                $goods_attr[] = array(
                    'goods_sn'      => & $goods_sn,
                    'attr_id'       => $attr_values[$p]['attr_id'],
                    'attr_value_id' => $attr_values[$p]['attr_value_id'],
                    'is_delete'     => UNDELETED,
                    'create_admin'  => & $create_admin,
                    'create_time'   => & $create_time,
                );
            }
        }
        /* 校验属性结束 */

        /* 校验描述开始 */
        if( $params['desc'] )
        {
            $goods_desc = array(
                'goods_sn'     => & $goods_sn,
                'desc'         => clean_html($params['desc']),
                'type'         => GOODS_DESC_TYPE_NORMAL,
                'is_delete'    => UNDELETED,
                'create_admin' => & $create_admin,
                'create_time'  => & $create_time,
            );
        }
        /* 校验描述结束 */
        
        // 写入
        $goods['status']       = GOODS_STATUS_ON;
        $goods['is_delete']    = UNDELETED;
        $goods['goods_sn']     = & $goods_sn;
        $goods['create_admin'] = & $create_admin;
        $goods['create_time']  = & $create_time;

        if( ! $goods_sn = $this->gen_goods_sn())
        {
            $this->set_error("新增商品失败：无法生成商品编号。");
            return FALSE;
        }

        $this->load->dao('Goods_dao');
        if( ! $this->Goods_dao->insert($goods))
        {
            $this->set_error("新增商品失败：无法写入数据库。");
            return FALSE;
        }

        if( $goods_attr )
        {
            $this->load->dao('Goods_attr_dao');
            $this->Goods_attr_dao->insert_batch($goods_attr);
        }

        if( $goods_desc )
        {
            $this->load->dao('Goods_desc_dao');
            $this->Goods_desc_dao->insert($goods_desc);
        }

        return $goods_sn;
    }

    // --------------------------------------------------------------------
    
    /**
     * [编辑商品]
     * @param  [string] $goods_sn   [商品编码]
     * @param  [array]  $params     [所有信息的数组]
     * @return [bool]
     */
    public function edit_goods($goods_sn, Array $params)
    {
        $params = array(
            'name'        => $params['name']        ? xss_clean(trim($params['name']))        : NULL,
            'subname'     => $params['subname']     ? xss_clean(trim($params['subname']))     : NULL,
            'type'        => $params['type']        ? xss_clean(trim($params['type']))        : NULL,
            'brand_sn'    => $params['brand_sn']    ? xss_clean(trim($params['brand_sn']))    : NULL,
            'category_id' => $params['category_id'] ? xss_clean(trim($params['category_id'])) : NULL,
            'base_price'  => $params['base_price']  ? xss_clean(trim($params['base_price']))  : NULL,
            'attr_values' => $params['attr_values'] ? (array)$params['attr_values']           : NULL,
            'desc'        => $params['desc']        ? trim($params['desc'])                   : NULL,
        );
        
        $goods        = array();
        $goods_attr   = array();
        $category     = array();
        $goods_desc   = array();
        $create_admin = login_info('admin_id');
        $create_time  = now_str();

        /* 校验商品编码开始 */
        if( ! $goods = $this->get_goods($goods_sn))
        {
            $this->set_error("编辑商品失败：商品编码不正确。[{$goods_sn}]。");
            return FALSE;
        }
        $goods_sn = $goods['goods_sn'];
        /* 校验商品编码结束 */

        /* 校验分类开始 */
        if( isset($params['category_id']) )
        {
            if( ! validate($params['category_id'], 'category_id') )
            {
                $this->set_error("编辑商品失败：分类ID不正确。[{$params['category_id']}]。");
                return FALSE;
            }
            $this->load->dao('Category_dao');
            $category = $this->Category_dao->get_one(array(
                'category_id' => $params['category_id'],
                'is_delete'   => UNDELETED,
                'status'      => CATEGORY_STATUS_ON,
            ));
            if( ! $category )
            {
                $this->set_error("编辑商品失败：分类ID不正确。[{$params['category_id']}]。");
                return FALSE;
            }
            $goods['category_id'] = $params['category_id'];
        }
        /* 校验分类结束 */

        /* 校验名开始 */
        if( isset($params['name']) )
        {
            if( ! validate_length($params['name'], 1, 50) )
            {
                $this->set_error("编辑商品失败：商品名最少1个字最多50个字。[{$params['name']}]。");
                return FALSE;
            }

            $this->load->dao('Goods_dao');
            $count = $this->Goods_dao->count(array(
                'goods_sn <>' => $goods_sn,
                'status'      => GOODS_STATUS_ON,
                'name'        => $params['name'],
                'is_delete'   => UNDELETED,
            ));

            if( $count > 0)
            {
                $this->set_error("编辑商品失败：商品名已存在。[{$params['name']}]。");
                return FALSE;
            }
            $goods['name'] = $params['name'];
        }
        /* 校验名结束 */

        /* 校验英文名开始 */
        if( isset($params['subname']) )
        {
            if( ! validate_length($params['subname'], 1, 50) )
            {
                $this->set_error("编辑商品失败：商品英文名最少1个字最多50个字。[{$params['subname']}]。");
                return FALSE;
            }

            $this->load->dao('Goods_dao');
            $count = $this->Goods_dao->count(array(
                'goods_sn <>' => $goods_sn,
                'status'      => GOODS_STATUS_ON,
                'subname'     => $params['subname'],
                'is_delete'   => UNDELETED,
            ));

            if( $count > 0)
            {
                $this->set_error("编辑商品失败：商品英文名已存在。[{$params['subname']}]。");
                return FALSE;
            }
            $goods['subname'] = $params['subname'];
        }
        /* 校验英文名结束 */

        /* 校验价格开始 */
        if( isset($params['base_price']) )
        {
            $base_price = moneyval($params['base_price']);
            if( $base_price < 0 )
            {
                $this->set_error("编辑商品失败：商品价格必须大于零。[{$params['base_price']}]。");
                return FALSE;
            }

            $goods['base_price'] = $base_price;
        }
        /* 校验价格结束 */

        /* 校验类型开始 */
        if( isset($params['type']) )
        {
            $goods_type = $this->config->item('goods_type');
            if( ! $goods_type[$params['type']] )
            {
                $this->set_error("编辑商品失败：未知的商品类型。[{$params['type']}]。");
                return FALSE;
            }
            $goods['type'] = $params['type'];
        }
        /* 校验类型结束 */

        /* 校验品牌开始 */
        if( isset($params['brand_sn']) )
        {
            if( ! validate($params['brand_sn'], 'brand_sn') )
            {
                $this->set_error("编辑商品失败：品牌编码不正确。[{$params['brand_sn']}]。");
                return FALSE;
            }
            $this->load->dao('Brand_dao');
            $count = $this->Brand_dao->count(array(
                'brand_sn' => $params['brand_sn'],
                'status'   => BRAND_STATUS_ON,
                'is_delete'=> UNDELETED,
            ));
            if( $count <= 0 )
            {
                $this->set_error("编辑商品失败：无法找到品牌。[{$params['brand_sn']}]。");
                return FALSE;
            }
            $goods['brand_sn'] = $params['brand_sn'];
        }
        /* 校验品牌结束 */

        /* 校验属性开始 */
        if( isset($params['attr_values']))
        {
            $this->load->dao('Attr_group_dao');
            $attr_group = $this->Attr_group_dao->get_one(array(
                'attr_group_id' => $category['attr_group_id'],
                'status'        => ATTR_GROUP_STATUS_ON,
                'is_delete'     => UNDELETED,
            ));

            if( ! $attr_group )
            {
                $this->set_error("编辑商品失败：无法找到属性模版。[{$category['attr_group_id']}]。");
                return FALSE;
            }

            $this->load->dao('Attr_dao');
            $attrs = $this->Attr_dao->get(
                array(
                    'attr_group_id' => $category['attr_group_id'],
                    'status'        => ATTR_STATUS_ON,
                    'is_delete'     => UNDELETED,
                ),
                array(
                    'attr_id',
                )
            );
            $attr_ids = array_pick($attrs, 'attr_id');

            $this->load->dao('Attr_value_dao');
            $attr_values = $this->Attr_value_dao->get_in(
                array('attr_id' => $attr_ids),
                array(
                    'status'        => ATTR_VALUE_STATUS_ON,
                    'is_delete'     => UNDELETED,
                ),
                array(
                    'attr_id',
                    'attr_value_id'
                )
            );

            array_change_key($attr_values, 'attr_value_id');

            foreach ($params['attr_values'] as $p) 
            {
                if( ! validate($p, 'ATTR_VALUE_ID') )
                {
                    $this->set_error("编辑商品失败：属性值ID不正确。[{$p}]。");
                    return FALSE;
                }

                if( ! $attr_values[$p] )
                {
                    $this->set_error("编辑商品失败：商品没有这个属性值。[{$p}]。");
                    return FALSE;
                }

                $goods_attr[] = array(
                    'goods_sn'      => & $goods_sn,
                    'attr_id'       => $attr_values[$p]['attr_id'],
                    'attr_value_id' => $attr_values[$p]['attr_value_id'],
                    'is_delete'     => UNDELETED,
                    'create_admin'  => & $create_admin,
                    'create_time'   => & $create_time,
                    'update_admin'  => & $create_admin,
                    'update_time'   => & $create_time,
                );
            }
        }
        /* 校验属性结束 */

        /* 校验描述开始 */
        if( $params['desc'] )
        {
            $goods_desc = array(
                'goods_sn'     => & $goods_sn,
                'desc'         => clean_html($params['desc']),
                'type'         => GOODS_DESC_TYPE_NORMAL,
                'is_delete'    => UNDELETED,
                'create_admin' => & $create_admin,
                'create_time'  => & $create_time,
            );
        }
        /* 校验描述结束 */

        if( $goods )
        {
            // 写入
            $goods['create_admin'] = & $create_admin;
            $goods['create_time']  = & $create_time;

            $this->load->dao('Goods_dao');
            if( ! $this->Goods_dao->update(
                $goods,
                array('goods_sn'=>$goods_sn)
            ))
            {
                $this->set_error("编辑商品失败：无法写入数据库。");
                return FALSE;
            }
        }

        //如果切换分类，自动把新属性模版的属性全部打开，其他关闭
        if( $goods['category_id'] && ! $goods_attr)
        {
            $this->load->dao('Attr_group_dao');
            $attr_group = $this->Attr_group_dao->get_one(array(
                'attr_group_id' => $category['attr_group_id'],
                'status'        => ATTR_GROUP_STATUS_ON,
                'is_delete'     => UNDELETED,
            ));

            if( $attr_group )
            {
                $this->load->dao('Attr_dao');
                $attrs = $this->Attr_dao->get(
                    array(
                        'attr_group_id' => $category['attr_group_id'],
                        'status'        => ATTR_STATUS_ON,
                        'is_delete'     => UNDELETED,
                    ),
                    array(
                        'attr_id',
                    )
                );

                $attr_ids = array_pick($attrs, 'attr_id');
            }

            $this->load->dao('Goods_attr_dao');
            
            // 全部设为不可见
            $this->Goods_attr_dao->update(
                array('is_delete'=> DELETED),
                array('goods_sn' => $goods_sn)
            );
            if($attr_ids)
            {
                // 提交部分为可见
                $this->Goods_attr_dao->update_in(
                    array('is_delete' => UNDELETED),
                    array('attr_id' => $attr_ids)
                );
            }
        }

        if( $goods_attr )
        {
            $this->load->dao('Goods_attr_dao');
            // 全部设为不可见
            $this->Goods_attr_dao->update(
                array('is_delete'=> DELETED),
                array('goods_sn' => $goods_sn)
            );
            // replace 提交部分为可见
            $this->Goods_attr_dao->replace_batch($goods_attr);
        }

        if( $goods_desc )
        {
            $this->load->dao('Goods_desc_dao');
            $this->Goods_desc_dao->delete(
                array(
                    'goods_sn' => $goods_sn,
                    'is_delete'=> UNDELETED,
                )
            );
            $this->Goods_desc_dao->insert($goods_desc);
        }

        return $goods_sn;
    }

    // --------------------------------------------------------------------
    
    /**
     * [生成商品图片]
     * @param  [string]         $file [zip包路径]
     * @return [array/false]
     */
    public function gen_goods_img($file)
    {
        $max_item   = self::$MAX_UPLOAD_ITEM;// 最大一次上传商品数
        $store_path = self::$IMG_PATH;       // 图片新目录

        if( ! file_exists($file) || 
            ! ($pathinfo = pathinfo($file))
        )
        {
            $this->set_error("生成商品图片失败：文件不存在。[{$file}]。");
            return FALSE;
        }

        // 解压文件到TEMP目录
        $path = TEMP_PATH.'/'.$pathinfo['filename'];
        $zip  = new ZipArchive;
        if( $zip->open($file) === TRUE)
        {
            $zip->extractTo($path);
            $zip->close();
        }

        $this->load->library('image_lib'); 

        // 遍历临时目录
        $response = array();
        $dir = opendir($path);
        while (($goods_sn = readdir($dir)) !== FALSE && $max_item >= 0 )
        {
            if($goods_sn == '.' || $goods_sn === '..')
                continue;

            // 验证文件夹名称
            if( ! validate($goods_sn, 'GOODS_SN') )
            {
                $response[$goods_sn]['folder'] = "文件夹名称不正确。{$goods_sn}";
                continue;
            }
            else
            {
                $response[$goods_sn]['folder'] = TRUE;
            }

            // 生成缩略图
            for($i=1; $i<=self::$MAX_IMG; $i++)
            {
                // 图片是否存在
                $img = "{$path}/{$goods_sn}/{$i}.jpg";
                if( ! file_exists($img) )
                {
                    $response[$goods_sn]["pic{$i}"] = "{$i}.jpg 不存在。";
                    continue;
                }

                // 不存在 创建目录
                if( ! file_exists("{$store_path}{$goods_sn}") )
                {
                    @mkdir("{$store_path}{$goods_sn}", DIR_WRITE_MODE);
                }

                // COPY 图片到前台目录
                $origin_img = FRONTEND_DATA_PATH."/goods/{$goods_sn}/{$i}_origin.jpg";
                if( ! copy($img, $origin_img) )
                {
                    $response[$goods_sn]["pic{$i}"] = "图片{$i}.jpg 无法复制。";
                    continue;
                }
                // 生成缩略图
                $config['image_library']  = 'gd2';
                $config['source_image']   = FRONTEND_DATA_PATH."/goods/{$goods_sn}/{$i}_origin.jpg";
                $config['maintain_ratio'] = TRUE;
                $config['quality']        = 100;
                $config['width']          = 50;
                $config['height']         = 50;
                $config['new_image']      = FRONTEND_DATA_PATH."/goods/{$goods_sn}/{$i}_small.jpg";

                $this->image_lib->initialize($config);
                $this->image_lib->resize();
                $this->image_lib->clear();

                                // 生成缩略图
                $config['image_library']  = 'gd2';
                $config['source_image']   = FRONTEND_DATA_PATH."/goods/{$goods_sn}/{$i}_origin.jpg";
                $config['maintain_ratio'] = TRUE;
                $config['quality']        = 100;
                $config['width']          = 150;
                $config['height']         = 150;
                $config['new_image']      = FRONTEND_DATA_PATH."/goods/{$goods_sn}/{$i}_medium.jpg";

                $this->image_lib->initialize($config);
                $this->image_lib->resize();
                $this->image_lib->clear();
                
                $response[$goods_sn]["pic{$i}"] = TRUE;
            }

            $max_item--;
        }
        closedir($dir);

        // 删除压缩文档
        @unlink($file);

        return $response;
    }
}